package com.tourex.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;

import com.tourex.thirdparty.cache.DiskLruCache;

/**
 * @author wangpeng
 * 
 */
public class DiskLruCacheUtils {

	public static final String object = "object";
	public static final String bitmap = "bitmap";

	public static boolean save(Context context, String cacheDirName,
			String cacheFileName, InputStream inputStream) {
		OutputStream output = null;
		try {
			DiskLruCache mDiskLruCache = open(context, cacheDirName);
			DiskLruCache.Editor mDiskLruEditor;
			String key = hashKeyForDisk(cacheFileName);
			mDiskLruEditor = mDiskLruCache.edit(key);
			output = mDiskLruEditor.newOutputStream(0);

			if (BaseUtils.inputStreamToOutputStream(inputStream, output))
				mDiskLruEditor.commit();
			else
				mDiskLruEditor.abort();

			mDiskLruCache.flush();
			return true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (output != null)
					output.close();
				if (inputStream != null)
					inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	public static InputStream get(Context context, String cacheDirName,
			String cacheFileName) {
		InputStream input = null;
		try {
			DiskLruCache mDiskLruCache = open(context, cacheDirName);
			String key = hashKeyForDisk(cacheFileName);
			DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
			if (snapShot != null) {
				input = snapShot.getInputStream(0);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return input;
	}

	public static boolean remove(Context context, String cacheDirName,
			String cacheFileName) {
		try {
			DiskLruCache mDiskLruCache = open(context, cacheDirName);
			String key = hashKeyForDisk(cacheFileName);
			mDiskLruCache.remove(key);
			return true;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}

	private static DiskLruCache open(Context context, String cacheDirName) {
		DiskLruCache mDiskLruCache = null;
		try {
			File cacheDir = getDiskCacheDir(context, cacheDirName);
			if (!cacheDir.exists()) {
				cacheDir.mkdirs();
			}
			mDiskLruCache = DiskLruCache.open(cacheDir, getAppVersion(context),
					1, 10 * 1024 * 1024);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return mDiskLruCache;
	}

	private static File getDiskCacheDir(Context context, String uniqueName) {
		String cachePath;
		if (Environment.MEDIA_MOUNTED.equals(Environment
				.getExternalStorageState())
				|| !Environment.isExternalStorageRemovable()) {
			cachePath = context.getExternalCacheDir().getPath();
		} else {
			cachePath = context.getCacheDir().getPath();
		}
		return new File(cachePath + File.separator + uniqueName);
	}

	private static int getAppVersion(Context context) {
		try {
			PackageInfo info = context.getPackageManager().getPackageInfo(
					context.getPackageName(), 0);
			return info.versionCode;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return 1;
	}

	public static String hashKeyForDisk(String key) {
		String cacheKey;
		try {
			final MessageDigest mDigest = MessageDigest.getInstance("MD5");
			mDigest.update(key.getBytes());
			cacheKey = bytesToHexString(mDigest.digest());
		} catch (NoSuchAlgorithmException e) {
			cacheKey = String.valueOf(key.hashCode());
		}
		return cacheKey;
	}

	private static String bytesToHexString(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < bytes.length; i++) {
			String hex = Integer.toHexString(0xFF & bytes[i]);
			if (hex.length() == 1) {
				sb.append('0');
			}
			sb.append(hex);
		}
		return sb.toString();
	}
}
